package com.ellecity06.common.utils

import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.provider.MediaStore.Video
import android.webkit.MimeTypeMap
import androidx.annotation.RequiresApi
import com.ellecity06.common.R
import com.ellecity06.common.ktx.showToast
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.Locale


/**
 * @Author      JsonPai
 * @CreateDate  2024/10/26
 * @Description 文件工具类
 */
object FileUtil {


    // ========================================== 文件保存 ==========================================
    /**
     * 保存图片文件在app外部存储（公共存储）
     *
     * @param imageName 图片名称
     * @param imageFile 图片文件
     * @param imageBitmap  图片Bitmap，和图片Bitmap二选一
     * @param imageFileExistsTips 图片文件件存在提示
     */
    fun saveImageFileToExternal(
        context: Context?,
        imageName: String,
        imageFile: File? = null,
        imageBitmap: Bitmap? = null,
        imageFileExistsTips: Int = R.string.file_exists,
    ) {
        context?.let {
            if (imageBitmap == null && imageFile == null) {
                R.string.file_error.showToast()
                return
            }

            // 判断Android SDK版本，适配安卓10存储
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                // Android 10以上
                saveFileToExternalOfQAfter(
                    context = it,
                    imageName = imageName,
                    imageFile = imageFile,
                    imageBitmap = imageBitmap
                )

            } else {
                // Android 10以下
                saveFileToExternalOfQBefore(
                    context = it,
                    imageName = imageName,
                    imageFile = imageFile,
                    imageBitmap = imageBitmap,
                    imageFileExistsTips = imageFileExistsTips
                )
            }
        }
    }

    /**
     * 安卓10以上的保存公共文件
     */
    @RequiresApi(Build.VERSION_CODES.Q)
    private fun saveFileToExternalOfQAfter(
        context: Context,
        imageName: String,
        imageFile: File? = null,
        imageBitmap: Bitmap? = null,
    ) {
        // 输入流
        var inputStream: InputStream? = null
        // 输出流
        var outputStream: OutputStream? = null
        try {
            val resolver = context.contentResolver
            // 设置文件参数到ContentValues中
            val values = ContentValues()
            // 设置文件名
            values.put(MediaStore.Images.Media.DISPLAY_NAME, imageName)
            // 设置文件描述，这里以文件名代替
            values.put(MediaStore.Images.Media.DESCRIPTION, imageName)
            // 设置文件类型为image/*
            values.put(MediaStore.Images.Media.MIME_TYPE, "image/*")
            // 注意：MediaStore.Images.Media.RELATIVE_PATH需要targetSdkVersion=29
            // 故该方法只可在Android10及以上的手机上执行
            values.put(
                MediaStore.Images.Media.RELATIVE_PATH,
                publicFileQPath
            )
            // EXTERNAL_CONTENT_URI代表外部存储器
            val external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
            //insertUri表示文件保存的uri路径
            val insertUri = resolver.insert(external, values)
            outputStream = resolver.openOutputStream(insertUri!!)
            val file = if (imageFile != null) {
                imageFile
            } else {
                saveImageFileToInterior(
                    dirFile = defaultCacheFileDir,
                    fileName = imageName,
                    fileBitmap = imageBitmap
                )
                File("${defaultCacheFileDir.absolutePath}/${imageName}")
            }
            inputStream = FileInputStream(file)
            val byteArray = ByteArray(1024)
            var len: Int
            while (inputStream.read(byteArray).also { len = it } != -1) {
                outputStream?.write(byteArray, 0, len)
            }
            R.string.save_succeed.showToast()
        } catch (e: Exception) {
logD("", tr = e)
            R.string.save_failed.showToast()
        } finally {
            inputStream?.close()
            outputStream?.close()
        }
    }

    /**
     * 保存视频
     * @param context
     * @param file
     */
    fun saveVideo(context: Context, file: File) {
        //是否添加到相册
        val localContentResolver = context.contentResolver
        val localContentValues = getVideoContentValues(context, file, System.currentTimeMillis())
        val localUri = localContentResolver.insert(Video.Media.EXTERNAL_CONTENT_URI, localContentValues)
        context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri))
    }

    fun getVideoContentValues(paramContext: Context?, paramFile: File, paramLong: Long): ContentValues {
        val localContentValues = ContentValues()
        localContentValues.put("title", paramFile.name)
        localContentValues.put("_display_name", paramFile.name)
        localContentValues.put("mime_type", "video/mp4")
        localContentValues.put("datetaken", paramLong)
        localContentValues.put("date_modified", paramLong)
        localContentValues.put("date_added", paramLong)
        localContentValues.put("_data", paramFile.absolutePath)
        localContentValues.put("_size", paramFile.length())
        return localContentValues
    }


    fun broadcastVideoFileQ(
        context: Context, inputStream: InputStream, fileName: String
    ) {
        try {
            val dateTaken = System.currentTimeMillis()
            val values = ContentValues()
            values.put(Video.Media.TITLE, fileName)
            values.put(Video.Media.DISPLAY_NAME, fileName)
            values.put(Video.Media.DATE_TAKEN, dateTaken)
            values.put(Video.Media.DATE_MODIFIED, dateTaken / 1000)
            values.put(Video.Media.MIME_TYPE, "video/mp4")
            values.put(Video.Media.RELATIVE_PATH, publicFileQPath)
            val uri = context.contentResolver
                .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
            if (uri != null) {
                try {
                    val pfd = context.contentResolver.openFileDescriptor(uri, "rw", null)
                    //文件输出流
                    val outputStream = FileOutputStream(pfd!!.fileDescriptor)
                    val bufferSize = 1024
                    val buff = ByteArray(bufferSize)
                    var rc = 0
                    try {
                        while ((inputStream.read(buff, 0, bufferSize).also { rc = it }) > 0) {
                            outputStream.write(buff, 0, rc)
                        }
                        outputStream.flush()
                        outputStream.close()
                        inputStream.close()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                } finally {
//                    if (listener != null) {
//                        listener.onScanCompleted(FolderHelper.getOrCreateSaveLocation() + fileName, uri, 0)
//                    }
                }
            } else {
                throw RuntimeException()
            }
        } catch (tr: Throwable) {
            tr.printStackTrace()
        }
    }

    /**
     * 安卓10以下的保存公共文件
     */
    private fun saveFileToExternalOfQBefore(
        context: Context,
        imageName: String,
        imageFile: File? = null,
        imageBitmap: Bitmap? = null,
        imageFileExistsTips: Int = R.string.file_exists,
    ) {
        var outputStream: FileOutputStream? = null
        try {
            // 判断文件是否存在，如果不存在 就mkdirs()创建此文件夹
            val saveDir = publicFile
            if (!saveDir.exists()) {
                saveDir.mkdirs()
            }

            // 将要保存的文件
            val saveFile = File(publicFile, imageName)
            if (saveFile.exists()) {
                imageFileExistsTips.showToast()
                return
            }
            // 构建输出流
            outputStream = FileOutputStream(saveFile)
            // 获取图片Bitmap
            val bitmap = imageBitmap ?: BitmapFactory.decodeFile(imageFile?.absolutePath)
            // compress到输出outputStream
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
            // 获得图片的uri
            val uri = Uri.fromFile(saveFile)
            // 发送广播通知更新图库
            context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri))
            R.string.save_succeed.showToast()
        } catch (e: Exception) {
            R.string.save_failed.showToast()
        } finally {
            outputStream?.close()
        }
    }

    /**
     * 保存图片文件在app内部文件
     *
     * @param dirFile 保存文件夹
     * @param fileName 文件名
     * @param fileBitmap 文件Bitmap
     */
    private fun saveImageFileToInterior(dirFile: File, fileName: String, fileBitmap: Bitmap?) {
        if (fileBitmap != null) {
            fileBitmap.let { bitmap ->
                // 判断文件是否存在，如果不存在 就mkdirs()创建此文件夹
                if (!dirFile.exists()) {
                    dirFile.mkdirs()
                }

                // 将要保存的图片文件
                val saveFile = File(dirFile.absolutePath, fileName)
                // 如果文件不存在才做保存操作，存在时不做任何操作
                if (!saveFile.exists()) {
                    // 构建输出流
                    val outputStream = FileOutputStream(saveFile)
                    // compress到输出outputStream
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
                }
            }

        } else {
            R.string.save_failed.showToast()
        }
    }

    // ========================================== 文件删除 ==========================================
    /**
     * 删除一个或多个文件
     */
    fun deleteFile(vararg files: File?) {
        files.forEach { file ->
            file?.let {
                if (it.isFile) {
                    it.delete()
                }
            }
        }
    }

    /**
     * 删除某个文件夹的所有文件
     */
    fun deleteDirAllFile(dir: File?) {
        dir?.let {
            if (it.isDirectory) {
                val files = it.listFiles()
                if (files != null) {
                    for (file in files) {
                        if (file.isFile) {
                            file.delete()
                        }
                    }
                }
            }
        }
    }

    fun getRandomImageName(): String {
        return "jdg_${System.currentTimeMillis()}.png"
    }

    fun isVideo(file: File): Boolean {
        var extension: String? = getFileExtension(file.name)
        if (extension != null) {
            extension = extension.lowercase(Locale.getDefault())
            // 常见的视频格式扩展名
            val commonVideoExtensions = arrayOf("mp4", "mov", "avi", "mpg", "mkv", "webm", "3gp", "m4v", "flv")
            for (videoExtension in commonVideoExtensions) {
                if (videoExtension == extension) {
                    return true
                }
            }
        }
        // 检查MIME类型
        val mimeType: String? = getMimeType(file)
        if (mimeType != null) {
            return mimeType.startsWith("video/")
        }
        return false
    }
    private fun getFileExtension(fileName: String): String? {
        return if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
            fileName.substring(fileName.lastIndexOf(".") + 1)
        } else {
            null
        }
    }

    private fun getMimeType(file: File): String? {
        val extension = getFileExtension(file.name)
        if (extension != null) {
            val mime: MimeTypeMap = MimeTypeMap.getSingleton()
            return mime.getMimeTypeFromExtension(extension.lowercase(Locale.getDefault()))
        }
        return null
    }
    // ========================================== 文件目录 ==========================================
    /**
     * 获取默认缓存目录
     */
    val defaultCacheFileDir: File
        get() {
            return File(
                appContext.externalCacheDir,
                "jdg"
            )
        }

    /**
     * 公共目录文件
     */
    val publicFile: File
        get() {
            return File(
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                "jdg"
            )
        }

    /**
     * 公共目录文件（安卓10及以上）
     */
    val publicFileQPath: String
        get() = "${Environment.DIRECTORY_PICTURES}/jdg"
}